
/**
\file
Definition of the viewport base class.
\author Sean Tromans
*/

#ifndef	RAINBOW_VIEWPORT_HPP
#define	RAINBOW_VIEWPORT_HPP

#include <rainbow/viewport/viewport_fwd.hpp>
#include <rainbow/viewport/pass/pass_fwd.hpp>
#include <rainbow/viewport/viewport_stack.hpp>
#include <rainbow/exception/exception.hpp>

#include <sun/lua/lua_fwd.hpp>
#include <needs_more_ninja/interface.hpp>
#include <needs_more_ninja/template/hashed_string.hpp>
#include <utility>
#include <vector>

namespace rainbow
{

	/**
	An exception to be thrown if a user attempts to add more than one pass with the same name to a viewport.
	\author Sean Tromans
	*/
	class name_already_used : public exception
	{
		public:

			name_already_used( std::string const & name )
				:	exception( nmn::create_string( "rainbow::name_already_used: Attempted to create more than one pass with the name \"%1%\"", name )  )
			{ }
	};

	/**
	Base viewport class.
	Contains multiple rendering passes which are to be drawn to this viewport.
	\author Sean Tromans
	*/
	class viewport : public nmn::interface_
	{
		//
		//	Public Member Functions
		//
		public:

			/**
			Adds a pass to the viewport.
			@param name The unique name to be given to this pass.
			@param pass The pass to add to the viewport.
			\throw name_already_used
			\author Sean Tromans
			*/
			void add_pass( nmn::hashed_string const & name, pass_ptr pass );

			/**
			Retreives a pass from the viewport.
			@param name The unique name of the pass.
			@return The pass requested. Null if no pass with the unique name \c name existed.
			\author Sean Tromans
			*/
			pass_ptr get_pass( nmn::hashed_string const & name ) const;

			/**
			Removes a pass to from the viewport.
			@param name The unique name of the pass.
			@return The pass which was just removed. Null if no pass with the unique name \c name existed.
			\author Sean Tromans
			*/
			pass_ptr remove_pass( nmn::hashed_string const & name );

			/**
			Triggers this viewport to find all of the objects it would like to draw for each pass.
			@param step_fraction How far between logic updates this frame is.
			@param stack The viewport stack to add any additional required viewports to.
			\author Sean Tromans
			*/
			virtual void build_render_queue( float step_fraction, viewport_stack & stack ) = 0;

			/**
			Informs the viewport that all dependencies have been met and it is now time to draw each of its passes.
			@param step_fraction How far between logic updates this frame is.
			\author Sean Tromans
			*/
			virtual void draw( float step_fraction ) = 0;

		//
		//	Protected Member Types
		//
		protected:

			/** Named and Pass pair type. */
			typedef std::pair< nmn::hashed_string, pass_ptr >	pass_pair_t;

			/** Collection of all passes used by this viewport, in order. */
			typedef std::vector< pass_pair_t >	pass_vector_t;

		//
		//	Protected Member Variables
		//
		protected:

			pass_vector_t	m_passes;	///< All the passes contained within this viewport.

		//
		//	Static Member Functions
		//
		public:

			/**
			Exposes the viewport to lua.
			@param L The Lua State being initialised.
			\author Sean Tromans.
			*/
			static void lua_interface( lua_State * L );
	};

};

#endif	//RAINBOW_VIEWPORT_HPP
